(* Erreurs possibles :
- get_first_word -> la regex \\t n'est peut-être pas celle qui sépare en fonction de blancs, je crois qu'il y en a une plus commune quelque part ailleurs
*)

open Str

let get_list_lines s = split (regexp "\n") s

let explode s =
	let rec f acc = function
		| -1 -> acc
		| k -> f (s.[k] :: acc) (k - 1)
		in f [] (String.length s - 1)

let rec print_tabs = function
	0 -> ""
	|n when n > 0 -> "	" ^ print_tabs (n-1)
	|n -> ""

let get_nb_acc s = 
	let splits = explode s in
		let rec doIt = function
			[] -> 0
			|e::l when e = '{' -> 1 + doIt l
			|e::l when e = '}' -> -1 + doIt l
			|e::l -> doIt l
			in doIt splits 

let get_first_word s =
	let splits = split (regexp "[ /		]+") s in
		let rec doIt = function	
			[] -> ""
			|e::l -> e
			in doIt splits

let get_last_word s =
	let splits = split (regexp "[ /		]+") s in
		let rec doIt = function	
			[] -> ""
			|e::[] -> e
			|e::l -> doIt l
			in doIt splits

let last_char s =
	let splits = explode s in
		let rec doIt = function
			[] -> '~';
			|e::[] -> e
			|e::l -> doIt l
			in doIt splits

let first_char s =
	let splits = explode s in
		let rec doIt = function
			[] -> '~';
			|e::l -> e
			in doIt splits 

let get_last_char s = last_char (get_last_word s)

let get_first_char s = first_char (get_first_word s)

let get_nb str s =
	let splits = split (regexp "[ /		]+") s in
		let rec doIt st = function
			[] -> 0
			|e::l when e = st -> 1 + doIt st l
			|e::l -> doIt st l
			in doIt str splits

let string_of_char n = String.make 1 n

let remove_all_tabs s =
	let splits = explode s in
		let rec doIt b = function
			[] -> ""
			|e::l when e = '	' & b -> doIt b l
			|e::l when e = ' ' & b -> doIt b l
			|e::l -> (string_of_char e) ^ (doIt false l)
			in
				doIt true splits

let rec remove_all_all_tabs = function
	[] -> []
	|e::l -> (remove_all_tabs e) :: remove_all_all_tabs l

let refacto_c s =
	let rec doIt i = function	
		[] -> ""
		|e::l when i < (i + get_nb_acc e) -> print_tabs (i) ^ e ^ "\n" ^	doIt (i + get_nb_acc e) l
		|e::l -> print_tabs (i + get_nb_acc e) ^ e ^ "\n" ^	doIt (i + get_nb_acc e) l
		in doIt 0 (get_list_lines (remove_all_tabs s))

(*lcu
lol = list_of_let*)

let refacto_caml s =
	let rec doIt str lcu (*lol*) isarg i = match str with
		[] -> ""
		|e::l when (lcu <> ';' & get_first_word e = "") -> "\n" ^ doIt l '~' (*[]*) false 0
		|e::l -> print_tabs 
		(i + (if (lcu = '=') then 1 else 0) - get_nb "end" e - get_nb "done" e) ^ 
		e ^ 
		"\n" ^ 
		doIt 
		l 
		(get_last_char e)
		(get_first_char e = '~') 
		(if (i + 
		get_nb "function" e +
		get_nb "with" e +
		get_nb "class" e +
		(if (get_nb "in" e > 0) then get_nb "in" e else 0) +
		(if (lcu = '=') then 1 else 0) +
		get_nb "do" e -
		get_nb "done" e +
		get_nb "begin" e -
		get_nb "end" e) <= 0 
		then 0 
		else 
		(i + 
		get_nb "function" e +
		get_nb "with" e +
		get_nb "class" e +
		(if (get_nb "in" e > 0) then get_nb "in" e else 0) +
		(if (lcu = '=') then 1 else 0) +
		get_nb "do" e -
		get_nb "done" e+
		get_nb "begin" e -
		get_nb "end" e))
		in doIt ( remove_all_all_tabs (get_list_lines s)) '~' (*[]*) false 0



(*
Quand on indente :
- si function ou with dans la ligne -> ligne d'après
		- last_word = "=" -> ligne d'après
		- si in dans la phrase -> ligne d'après
			- si do est dans la phrase -> lige d'après

On désindente :
si "in" est dans la phrase -> ligne actuelle
si done est dans la phrase -> ligne actuelle

RAZ =
	on remet à 0 si on tombe sur une ligne vide et que lastword de ligne d'avant <> ;
	
	Cas particulier :
	Si ~ en firstchar, alors on incremente sur ligne actuelle, et on ignore tous les ~ jusqu'à tomber sur un in (on ignore la décrem (== on increm)) ou une ràz.
		*)